package cn.yangsen.simplebeanmanager.tool;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;

import cn.yangsen.simplebeanmanager.annotation.Actualize;

public class ReflectTool
{
	public static Class<?> 获取封装类(Class<?> 基本类型)
	{
		if (基本类型 == boolean.class)
		{
			return Boolean.class;
		}
		else if (基本类型 == byte.class)
		{
			return Byte.class;
		}
		else if (基本类型 == char.class)
		{
			return Character.class;
		}
		else if (基本类型 == double.class)
		{
			return Double.class;
		}
		else if (基本类型 == float.class)
		{
			return Float.class;
		}
		else if (基本类型 == int.class)
		{
			return Integer.class;
		}
		else if (基本类型 == long.class)
		{
			return Long.class;
		}
		else if (基本类型 == short.class)
		{
			return Short.class;
		}
		else if (基本类型 == void.class)
		{
			return Void.class;
		}
		return null;
	}

	public static Field[] 获取类父类所有属性(Class<?> 类型)
	{
		return 获取类及其父类所有属性(类型.getSuperclass());
	}

	/**
	 * 某个类的所有申明非static的字段，即包括public、private和proteced，包括父类。 类型必须使用了 @Entity 注解才生效
	 * 
	 * @param 类型
	 * @return
	 */
	public static Field[] 获取类及其父类所有属性(final Class<?> 类型)
	{
		if (类型 == Object.class || 类型 == null)
		{
			return null;
		}

		Field[] 当前类型所有的属性 = 类型.getDeclaredFields();

		int 静态属性 = 0;
		for (int i = 0; i < 当前类型所有的属性.length; i++)
		{
			if (Modifier.isStatic(当前类型所有的属性[i].getModifiers()))
			{
				静态属性++;
				当前类型所有的属性[i] = null;
			}
		}
		if (静态属性 > 0)
		{
			Field[] tempF = new Field[当前类型所有的属性.length - 静态属性];
			int i = 0;
			for (int j = 0; j < 当前类型所有的属性.length; j++)
			{
				if(当前类型所有的属性[j] != null)
				{
					tempF[i] = 当前类型所有的属性[j];
					i++;
				}
			}
			当前类型所有的属性 = tempF;
		}

		Class<?> 上级类型 = 类型.getSuperclass();
		Field[] 上级类型所有的属性 = 获取类及其父类所有属性(上级类型);
		if (ArrayUtils.isNotEmpty(上级类型所有的属性))
		{
			if (ArrayUtils.isNotEmpty(当前类型所有的属性))
			{
				return ArrayUtils.addAll(上级类型所有的属性, 当前类型所有的属性);
			}
			return 上级类型所有的属性;
		}

		return 当前类型所有的属性;
	}

	/**
	 * 某个类的所有申明的字段，即包括public、private和proteced，包括子类(通过 @Actualize 查找)。 类型必须使用了 @Entity 注解才生效
	 * 
	 * @param 类型
	 * @return
	 */
	public static Field[] 获取类及其子类所有属性(final Class<?> 类型)
	{
		if (类型 == null)
		{
			return null;
		}

		Field[] 当前类型所有的属性 = 类型.getDeclaredFields();

		Actualize 实现申明 = 类型.getAnnotation(Actualize.class);
		if (实现申明 != null)
		{
			Class<?>[] 实现类集合 = 实现申明.value();
			for (Class<?> 实现类 : 实现类集合)
			{
				Field[] 实现类的属性 = 获取类及其子类所有属性(实现类);
				if (ArrayUtils.isNotEmpty(实现类的属性))
				{
					当前类型所有的属性 = ArrayUtils.addAll(当前类型所有的属性, 实现类的属性);
				}
			}
		}
		return 当前类型所有的属性;
	}

	public static Field 获取对象的属性(Class<?> 类型, String 属性名)
	{
		Field[] 所有属性 = 获取类及其父类所有属性(类型);
		for (Field field : 所有属性)
		{
			if (field.getName().equals(属性名))
			{
				return field;
			}
		}
		return null;
	}

	public static Field 获取对象的属性(Object 对象, String 属性名)
	{
		return 获取对象的属性(对象.getClass(), 属性名);
	}

	public static Object 获取对象的属性值(Object 对象, String 属性名)
	{
		Field 属性 = 获取对象的属性(对象, 属性名);
		return 获取对象的属性值(对象, 属性);
	}

	public static Object 获取对象的属性值(Object 对象, Field 属性)
	{
		if (对象 == null || 属性 == null)
		{
			return null;
		}
		Class<?> type = 属性.getType();

		if (type == boolean.class || type == Boolean.class)
		{
			return 执行方法(对象.getClass(), 对象, "is" + StringUtils.capitalize(属性.getName()));
		}
		else
		{
			return 执行方法(对象.getClass(), 对象, "get" + StringUtils.capitalize(属性.getName()));
		}
	}

	public static void 填充对象的属性值(Object 对象, Field 属性, Object 值)
	{
		if (对象 == null || 属性 == null)
		{
			return;
		}
		执行方法(对象.getClass(), 对象, "set" + StringUtils.capitalize(属性.getName()), 值);
	}

	public static Object 执行方法(Object 对象, String 方法名, Object... 参数)
	{
		if (对象 == null)
		{
			return null;
		}
		return 执行方法(对象.getClass(), 对象, 方法名, 参数);
	}

	public static <T> Object 执行方法(Class<? extends T> 类, T 对象, String 方法名, Object... 参数)
	{
		if (StringUtils.isEmpty(方法名))
		{
			return null;
		}
		Method 方法 = null;
		Class<?>[] parameterTypes = null;
		if (参数 != null)
		{
			List<Class<?>> list = new ArrayList<>();
			for (Object obj : 参数)
			{
				list.add(obj.getClass());
			}
			parameterTypes = list.toArray(new Class<?>[list.size()]);
		}
		try
		{
			方法 = 类.getMethod(方法名, parameterTypes);
		}
		catch (NoSuchMethodException e)
		{
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		catch (SecurityException e)
		{
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return 执行方法(对象, 方法, 参数);
	}

	public static Object 执行方法(Object 对象, Method 方法, Object... 参数)
	{
		if (方法 == null)
		{
			return null;
		}
		try
		{
			return 方法.invoke(对象, 参数);
		}
		catch (IllegalAccessException e)
		{
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		catch (IllegalArgumentException e)
		{
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		catch (InvocationTargetException e)
		{
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		return null;
	}

	public static Class<?>[] 获取子类(Class<?> 类型)
	{
		Actualize 实现申明 = 类型.getAnnotation(Actualize.class);
		if (实现申明 != null)
		{
			return 实现申明.value();
		}
		return null;
	}

	public static <T extends Annotation> T 获取枚举的注解(Class<T> 注解类型, Enum<?> 枚举)
	{
		Field 属性 = null;
		Class<?> 枚举类 = 枚举.getClass();
		try
		{
			属性 = 枚举类.getField(枚举.name());
		}
		catch (NoSuchFieldException e)
		{
			e.printStackTrace();
		}
		catch (SecurityException e)
		{
			e.printStackTrace();
		}
		if (属性 == null)
		{
			return null;
		}
		return 属性.getAnnotation(注解类型);
	}

	public static Object 构造一个新对象(Class<?> 类型)
	{
		if (类型 == Integer.class)
		{
			return Integer.valueOf(0);
		}
		else if (类型 == Float.class)
		{
			return Float.valueOf(0);
		}
		else if (类型 == Short.class)
		{
			return Short.valueOf((short) 0);
		}
		else if (类型 == Double.class)
		{
			return Double.valueOf(0);
		}
		try
		{
			return 类型.newInstance();
		}
		catch (InstantiationException | IllegalAccessException e)
		{
			e.printStackTrace();
		}
		return null;
	}
}
